// -*- mode: C++; c-file-style: "cc-mode" -*-
//*************************************************************************
//
// Copyright 2020 by Geza Lore. This program is free software; you can
// redistribute it and/or modify it under the terms of either the GNU
// Lesser General Public License Version 3 or the Perl Artistic License
// Version 2.0.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
//
//*************************************************************************

#include <cstdio>
#include <cstdlib>
#include <cstring>

// clang-format off
#if defined(NCSC)
// Used by NC's svdpi.h to pick up svLogicVecVal with _.aval and _.bval fields,
// rather than the IEEE 1800-2005 version which has _.a and _.b fields.
# define DPI_COMPATIBILITY_VERSION_1800v2012
#endif

#include "svdpi.h"

#if defined(VERILATOR)  // Verilator
# include "Vt_dpi_arg_input_type__Dpi.h"
typedef long long sv_longint_t;
typedef unsigned long long sv_longint_unsigned_t;
# define NO_SHORTREAL
# define CONSTARG const
#elif defined(VCS)  // VCS
# include "../vc_hdrs.h"
typedef long long sv_longint_t;
typedef unsigned long long sv_longint_unsigned_t;
# define NO_TIME
# define CONSTARG const
#elif defined(NCSC)  // NC
# include "dpi-exp.h"
# include "dpi-imp.h"
typedef long long sv_longint_t;
typedef unsigned long long sv_longint_unsigned_t;
# define NO_TIME
# define NO_INTEGER
# define NO_SHORTREAL
// Sadly NC does not declare pass-by reference input arguments as const
# define CONSTARG
#elif defined(MS)  // ModelSim
# include "dpi.h"
typedef int64_t sv_longint_t;
typedef uint64_t sv_longint_unsigned_t;
# define CONSTARG const
#else
# error "Unknown simulator for DPI test"
#endif
// clang-format on

//======================================================================
// Implementations of imported functions
//======================================================================

#define stop()                                                                 \
  do {                                                                         \
    printf(__FILE__ ":%d Bad value\n", __LINE__);                              \
    abort();                                                                   \
  } while (0)

void check_bvals(CONSTARG svLogicVecVal *v, unsigned n);
void check_bvals(CONSTARG svLogicVecVal *v, unsigned n) {
  for (unsigned i = 0; i < n; i++) {
    if (v[i].bval != 0) {
      printf(__FILE__ ":%d Bad svLogicVecVal bval\n", __LINE__);
      abort();
    }
  }
}

// Basic types as per IEEE 1800-2017 35.5.6
void i_byte(char i) {
  static int n = 0;
  if (i != 10 - n++)
    stop();
}

void i_byte_unsigned(unsigned char i) {
  static int n = 0;
  if (i != 20 - n++)
    stop();
}

void i_shortint(short i) {
  static int n = 0;
  if (i != 30 - n++)
    stop();
}

void i_shortint_unsigned(unsigned short i) {
  static int n = 0;
  if (i != 40 - n++)
    stop();
}

void i_int(int i) {
  static int n = 0;
  if (i != 50 - n++)
    stop();
}

void i_int_unsigned(unsigned i) {
  static int n = 0;
  if (i != 60 - n++)
    stop();
}

void i_longint(sv_longint_t i) {
  static int n = 0;
  if (i != 70 - n++)
    stop();
}

void i_longint_unsigned(sv_longint_unsigned_t i) {
  static int n = 0;
  if (i != 80 - n++)
    stop();
}

#ifndef NO_TIME
void i_time(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  if (i[0].aval != 90 - n++)
    stop();
  if (i[1].aval != 0)
    stop();
  check_bvals(i, 2);
}
#endif

#ifndef NO_INTEGER
void i_integer(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  if (i[0].aval != 100 - n++)
    stop();
  check_bvals(i, 1);
}
#endif

void i_real(double i) {
  static int n = 0;
  if (i != (-2.0 * n++ - 1.0) / 2.0)
    stop();
}

#ifndef NO_SHORTREAL
void i_shortreal(float i) {
  static int n = 0;
  if (i != (-4.0f * n++ - 1.0f) / 4.0f)
    stop();
}
#endif

void i_chandle(void *i) {
  static int n = 0;
  printf("i_chandle %d\n", n);
  if (i)
    stop();
  n++;
}

void i_string(const char *i) {
  static int n = 0;
  printf("i_string %d\n", n);
  if (n++ % 2 == 0) {
    if (strcmp(i, "World") != 0)
      stop();
  } else {
    if (strcmp(i, "Hello") != 0)
      stop();
  }
}

void i_bit(svBit i) {
  static int n = 0;
  printf("i_bit %d\n", n);
  if (i != !(n++ % 2))
    stop();
}

void i_logic(svLogic i) {
  static int n = 0;
  printf("i_logic %d\n", n);
  if (i != n++ % 2)
    stop();
}

// Basic types via typedefs
void i_byte_t(char i) {
  static int n = 0;
  if (i != 10 - n)
    stop();
  n += 2;
}

void i_byte_unsigned_t(unsigned char i) {
  static int n = 0;
  if (i != 20 - n)
    stop();
  n += 2;
}

void i_shortint_t(short i) {
  static int n = 0;
  if (i != 30 - n)
    stop();
  n += 2;
}

void i_shortint_unsigned_t(unsigned short i) {
  static int n = 0;
  if (i != 40 - n)
    stop();
  n += 2;
}

void i_int_t(int i) {
  static int n = 0;
  if (i != 50 - n)
    stop();
  n += 2;
}

void i_int_unsigned_t(unsigned i) {
  static int n = 0;
  if (i != 60 - n)
    stop();
  n += 2;
}

void i_longint_t(sv_longint_t i) {
  static int n = 0;
  if (i != 70 - n)
    stop();
  n += 2;
}

void i_longint_unsigned_t(sv_longint_unsigned_t i) {
  static int n = 0;
  if (i != 80 - n)
    stop();
  n += 2;
}

#ifndef NO_TIME
void i_time_t(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  if (i[0].aval != 90 - n)
    stop();
  if (i[1].aval != 0)
    stop();
  check_bvals(i, 2);
  n += 2;
}
#endif

#ifndef NO_INTEGER
void i_integer_t(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  if (i[0].aval != 100 - n)
    stop();
  check_bvals(i, 1);
  n += 2;
}
#endif

void i_real_t(double i) {
  static int n = 0;
  if (i != (-2.0 * n - 1.0) / 2.0)
    stop();
  n += 2;
}

#ifndef NO_SHORTREAL
void i_shortreal_t(float i) {
  static int n = 0;
  if (i != (-4.0f * n - 1.0f) / 4.0f)
    stop();
  n += 2;
}
#endif

void i_chandle_t(void *i) {
  static int n = 0;
  printf("i_chandle_t %d\n", n);
  if (i)
    stop();
  n++;
}

void i_string_t(const char *i) {
  static int n = 0;
  printf("i_string_t %d\n", n);
  if (n++ % 2 == 0) {
    if (strcmp(i, "World") != 0)
      stop();
  } else {
    if (strcmp(i, "Hello") != 0)
      stop();
  }
}

void i_bit_t(svBit i) {
  static int n = 0;
  printf("i_bit_t %d\n", n);
  if (i != !(n++ % 2))
    stop();
}

void i_logic_t(svLogic i) {
  static int n = 0;
  printf("i_logic_t %d\n", n);
  if (i != n++ % 2)
    stop();
}

// 2-state packed arrays
void i_array_2_state_1(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_array_2_state_1 %d\n", n);
  if ((*i & 1) != !(n++ % 2))
    stop();
}

void i_array_2_state_32(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_array_2_state_32 %d\n", n);
  if (*i != 0xffffffffU << n++)
    stop();
}

void i_array_2_state_33(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_array_2_state_33 %d\n", n);
  if (i[0] != 0xffffffffU << n++)
    stop();
  if ((i[1] & 1) != 1)
    stop();
}

void i_array_2_state_64(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_array_2_state_64 %d\n", n);
  if (i[0] != 0xffffffffU << n++)
    stop();
  if (i[1] != -1)
    stop();
}

void i_array_2_state_65(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_array_2_state_65 %d\n", n);
  if (i[0] != 0xffffffffU << n++)
    stop();
  if (i[1] != -1)
    stop();
  if ((i[2] & 1) != 1)
    stop();
}

void i_array_2_state_128(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_array_2_state_128 %d\n", n);
  if (i[0] != 0xffffffffU << n++)
    stop();
  if (i[1] != -1)
    stop();
  if (i[2] != -1)
    stop();
  if (i[3] != -1)
    stop();
}

// 2-state packed structures
void i_struct_2_state_1(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_struct_2_state_1 %d\n", n);
  if ((*i & 1) != !(n++ % 2))
    stop();
}

void i_struct_2_state_32(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_struct_2_state_32 %d\n", n);
  if (*i != 0xffffffffU << n++)
    stop();
}

void i_struct_2_state_33(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_struct_2_state_33 %d\n", n);
  if (i[0] != 0xffffffffU << n++)
    stop();
  if ((i[1] & 1) != 1)
    stop();
}

void i_struct_2_state_64(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_struct_2_state_64 %d\n", n);
  if (i[0] != 0xffffffffU << n++)
    stop();
  if (i[1] != -1)
    stop();
}

void i_struct_2_state_65(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_struct_2_state_65 %d\n", n);
  if (i[0] != 0xffffffffU << n++)
    stop();
  if (i[1] != -1)
    stop();
  if ((i[2] & 1) != 1)
    stop();
}

void i_struct_2_state_128(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_struct_2_state_128 %d\n", n);
  if (i[0] != 0xffffffffU << n++)
    stop();
  if (i[1] != -1)
    stop();
  if (i[2] != -1)
    stop();
  if (i[3] != -1)
    stop();
}

// 2-state packed unions
void i_union_2_state_1(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_union_2_state_1 %d\n", n);
  if ((*i & 1) != !(n++ % 2))
    stop();
}

void i_union_2_state_32(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_union_2_state_32 %d\n", n);
  if (*i != 0xffffffffU << n++)
    stop();
}

void i_union_2_state_33(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_union_2_state_33 %d\n", n);
  if (i[0] != 0xffffffffU << n++)
    stop();
  if ((i[1] & 1) != 1)
    stop();
}

void i_union_2_state_64(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_union_2_state_64 %d\n", n);
  if (i[0] != 0xffffffffU << n++)
    stop();
  if (i[1] != -1)
    stop();
}

void i_union_2_state_65(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_union_2_state_65 %d\n", n);
  if (i[0] != 0xffffffffU << n++)
    stop();
  if (i[1] != -1)
    stop();
  if ((i[2] & 1) != 1)
    stop();
}

void i_union_2_state_128(CONSTARG svBitVecVal *i) {
  static int n = 0;
  printf("i_union_2_state_128 %d\n", n);
  if (i[0] != 0xffffffffU << n++)
    stop();
  if (i[1] != -1)
    stop();
  if (i[2] != -1)
    stop();
  if (i[3] != -1)
    stop();
}

// 4-state packed arrays
void i_array_4_state_1(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_array_4_state_1 %d\n", n);
  if ((i->aval & 1) != !(n++ % 2))
    stop();
  check_bvals(i, 1);
}

void i_array_4_state_32(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_array_4_state_32 %d\n", n);
  if (i->aval != 0xffffffffU << n++)
    stop();
  check_bvals(i, 1);
}

void i_array_4_state_33(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_array_4_state_33 %d\n", n);
  if (i[0].aval != 0xffffffffU << n++)
    stop();
  if ((i[1].aval & 1) != 1)
    stop();
  check_bvals(i, 2);
}

void i_array_4_state_64(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_array_4_state_64 %d\n", n);
  if (i[0].aval != 0xffffffffU << n++)
    stop();
  if (i[1].aval != -1)
    stop();
  check_bvals(i, 2);
}

void i_array_4_state_65(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_array_4_state_65 %d\n", n);
  if (i[0].aval != 0xffffffffU << n++)
    stop();
  if (i[1].aval != -1)
    stop();
  if ((i[2].aval & 1) != 1)
    stop();
  check_bvals(i, 3);
}

void i_array_4_state_128(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_array_4_state_128 %d\n", n);
  if (i[0].aval != 0xffffffffU << n++)
    stop();
  if (i[1].aval != -1)
    stop();
  if (i[2].aval != -1)
    stop();
  if (i[3].aval != -1)
    stop();
  check_bvals(i, 4);
}

// 4-state packed structures
void i_struct_4_state_1(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_struct_4_state_1 %d\n", n);
  if ((i->aval & 1) != !(n++ % 2))
    stop();
  check_bvals(i, 1);
}

void i_struct_4_state_32(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_struct_4_state_32 %d\n", n);
  if (i->aval != 0xffffffffU << n++)
    stop();
  check_bvals(i, 1);
}

void i_struct_4_state_33(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_struct_4_state_33 %d\n", n);
  if (i[0].aval != 0xffffffffU << n++)
    stop();
  if ((i[1].aval & 1) != 1)
    stop();
  check_bvals(i, 2);
}

void i_struct_4_state_64(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_struct_4_state_64 %d\n", n);
  if (i[0].aval != 0xffffffffU << n++)
    stop();
  if (i[1].aval != -1)
    stop();
  check_bvals(i, 2);
}

void i_struct_4_state_65(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_struct_4_state_65 %d\n", n);
  if (i[0].aval != 0xffffffffU << n++)
    stop();
  if (i[1].aval != -1)
    stop();
  if ((i[2].aval & 1) != 1)
    stop();
  check_bvals(i, 3);
}

void i_struct_4_state_128(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_struct_4_state_128 %d\n", n);
  if (i[0].aval != 0xffffffffU << n++)
    stop();
  if (i[1].aval != -1)
    stop();
  if (i[2].aval != -1)
    stop();
  if (i[3].aval != -1)
    stop();
  check_bvals(i, 4);
}

// 4-state packed unions
void i_union_4_state_1(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_union_4_state_1 %d\n", n);
  if ((i->aval & 1) != !(n++ % 2))
    stop();
  check_bvals(i, 1);
}

void i_union_4_state_32(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_union_4_state_32 %d\n", n);
  if (i->aval != 0xffffffffU << n++)
    stop();
  check_bvals(i, 1);
}

void i_union_4_state_33(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_union_4_state_33 %d\n", n);
  if (i[0].aval != 0xffffffffU << n++)
    stop();
  if ((i[1].aval & 1) != 1)
    stop();
  check_bvals(i, 2);
}

void i_union_4_state_64(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_union_4_state_64 %d\n", n);
  if (i[0].aval != 0xffffffffU << n++)
    stop();
  if (i[1].aval != -1)
    stop();
  check_bvals(i, 2);
}

void i_union_4_state_65(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_union_4_state_65 %d\n", n);
  if (i[0].aval != 0xffffffffU << n++)
    stop();
  if (i[1].aval != -1)
    stop();
  if ((i[2].aval & 1) != 1)
    stop();
  check_bvals(i, 3);
}

void i_union_4_state_128(CONSTARG svLogicVecVal *i) {
  static int n = 0;
  printf("i_union_4_state_128 %d\n", n);
  if (i[0].aval != 0xffffffffU << n++)
    stop();
  if (i[1].aval != -1)
    stop();
  if (i[2].aval != -1)
    stop();
  if (i[3].aval != -1)
    stop();
  check_bvals(i, 4);
}

//======================================================================
// Check exported functions
//======================================================================

void set_bvals(svLogicVecVal *v, unsigned n);
void set_bvals(svLogicVecVal *v, unsigned n) {
  for (unsigned i = 0; i < n; i++)
    v[i].bval = 0;
}

void check_exports() {
  static int n = 0;

#ifndef NO_TIME
  svLogicVecVal x_time[2];
  svLogicVecVal x_time_t[2];
#endif
#ifndef NO_INTEGER
  svLogicVecVal x_integer[1];
  svLogicVecVal x_integer_t[1];
#endif

#ifndef NO_TIME
  set_bvals(x_time, 2);
  set_bvals(x_time_t, 2);
#endif
#ifndef NO_INTEGER
  set_bvals(x_integer, 1);
  set_bvals(x_integer_t, 1);
#endif

  // Basic types as per IEEE 1800-2017 35.5.6
  e_byte(10 + n);
  e_byte_unsigned(20 + n);
  e_shortint(30 + n);
  e_shortint_unsigned(40 + n);
  e_int(50 + n);
  e_int_unsigned(60 + n);
  e_longint(70 + n);
  e_longint_unsigned(80 + n);
#ifndef NO_TIME
  x_time[0].aval = 90 + n;
  x_time[1].aval = 0;
  e_time(x_time);
#endif
#ifndef NO_INTEGER
  x_integer[0].aval = 100 + n;
  e_integer(x_integer);
#endif
  e_real(1.0 * n + 0.5);
#ifndef NO_SHORTREAL
  e_shortreal(1.0f * n + 0.25f);
#endif
  e_chandle((n % 2) ? reinterpret_cast<void *>(&e_chandle) : NULL);
  e_string((n % 2) ? "World" : "Hello");
  e_bit(n % 2);
  e_logic(!(n % 2));

  // Basic types via tyepdef
  e_byte_t(10 + 2 * n);
  e_byte_unsigned_t(20 + 2 * n);
  e_shortint_t(30 + 2 * n);
  e_shortint_unsigned_t(40 + 2 * n);
  e_int_t(50 + 2 * n);
  e_int_unsigned_t(60 + 2 * n);
  e_longint_t(70 + 2 * n);
  e_longint_unsigned_t(80 + 2 * n);
#ifndef NO_TIME
  x_time_t[0].aval = 90 + 2 * n;
  x_time_t[1].aval = 0;
  e_time_t(x_time_t);
#endif
#ifndef NO_INTEGER
  x_integer_t[0].aval = 100 + 2 * n;
  e_integer_t(x_integer_t);
#endif
  e_real_t(1.0 * (2 * n) + 0.5);
#ifndef NO_SHORTREAL
  e_shortreal_t(1.0f * (2 * n) + 0.25f);
#endif
  e_chandle_t((n % 2) ? NULL : reinterpret_cast<void *>(&e_chandle_t));
  e_string_t((n % 2) ? "Hello" : "World");
  e_bit_t(n % 2);
  e_logic_t(!(n % 2));

  const int m = n == 0 ? 0 : n - 1;

  svBitVecVal b1[1];
  svBitVecVal b2[2];
  svBitVecVal b3[3];
  svBitVecVal b4[4];

  b3[0] = 0xffffffff;
  b4[0] = 0xffffffff;
  b4[1] = 0xffffffff;
  b4[2] = 0xffffffff;

  // 2-state packed arrays
  b1[0] = n % 2;
  e_array_2_state_1(b1);

  b1[0] = 0xffffffff >> n;
  e_array_2_state_32(b1);

  b2[1] = 1 >> n;
  b2[0] = 0xffffffff >> m;
  e_array_2_state_33(b2);

  b2[1] = 0xffffffff >> n;
  b2[0] = 0xffffffff;
  e_array_2_state_64(b2);

  b3[2] = 1 >> n;
  b3[1] = 0xffffffff >> m;
  e_array_2_state_65(b3);

  b4[3] = 0xffffffff >> n;
  e_array_2_state_128(b4);

  // 2-state packed structures
  b1[0] = n % 2;
  e_struct_2_state_1(b1);

  b1[0] = 0xffffffff >> n;
  e_struct_2_state_32(b1);

  b2[1] = 1 >> n;
  b2[0] = 0xffffffff >> m;
  e_struct_2_state_33(b2);

  b2[1] = 0xffffffff >> n;
  b2[0] = 0xffffffff;
  e_struct_2_state_64(b2);

  b3[2] = 1 >> n;
  b3[1] = 0xffffffff >> m;
  e_struct_2_state_65(b3);

  b4[3] = 0xffffffff >> n;
  e_struct_2_state_128(b4);

  // 2-state packed unions
  b1[0] = n % 2;
  e_union_2_state_1(b1);

  b1[0] = 0xffffffff >> n;
  e_union_2_state_32(b1);

  b2[1] = 1 >> n;
  b2[0] = 0xffffffff >> m;
  e_union_2_state_33(b2);

  b2[1] = 0xffffffff >> n;
  b2[0] = 0xffffffff;
  e_union_2_state_64(b2);

  b3[2] = 1 >> n;
  b3[1] = 0xffffffff >> m;
  e_union_2_state_65(b3);

  b4[3] = 0xffffffff >> n;
  e_union_2_state_128(b4);

  svLogicVecVal l1[1];
  svLogicVecVal l2[2];
  svLogicVecVal l3[3];
  svLogicVecVal l4[4];

  // bvals should be ignored, leave them un-initialized

  set_bvals(l1, 1);
  set_bvals(l2, 2);
  set_bvals(l3, 3);
  set_bvals(l4, 4);

  l3[0].aval = 0xffffffff;
  l4[0].aval = 0xffffffff;
  l4[1].aval = 0xffffffff;
  l4[2].aval = 0xffffffff;

  // 4-state packed arrays
  l1[0].aval = n % 2;
  e_array_4_state_1(l1);

  l1[0].aval = 0xffffffff >> n;
  e_array_4_state_32(l1);

  l2[1].aval = 1 >> n;
  l2[0].aval = 0xffffffff >> m;
  e_array_4_state_33(l2);

  l2[1].aval = 0xffffffff >> n;
  l2[0].aval = 0xffffffff;
  e_array_4_state_64(l2);

  l3[2].aval = 1 >> n;
  l3[1].aval = 0xffffffff >> m;
  e_array_4_state_65(l3);

  l4[3].aval = 0xffffffff >> n;
  e_array_4_state_128(l4);

  // 4-state packed structures
  l1[0].aval = n % 2;
  e_struct_4_state_1(l1);

  l1[0].aval = 0xffffffff >> n;
  e_struct_4_state_32(l1);

  l2[1].aval = 1 >> n;
  l2[0].aval = 0xffffffff >> m;
  e_struct_4_state_33(l2);

  l2[1].aval = 0xffffffff >> n;
  l2[0].aval = 0xffffffff;
  e_struct_4_state_64(l2);

  l3[2].aval = 1 >> n;
  l3[1].aval = 0xffffffff >> m;
  e_struct_4_state_65(l3);

  l4[3].aval = 0xffffffff >> n;
  e_struct_4_state_128(l4);

  // 4-state packed unions
  l1[0].aval = n % 2;
  e_union_4_state_1(l1);

  l1[0].aval = 0xffffffff >> n;
  e_union_4_state_32(l1);

  l2[1].aval = 1 >> n;
  l2[0].aval = 0xffffffff >> m;
  e_union_4_state_33(l2);

  l2[1].aval = 0xffffffff >> n;
  l2[0].aval = 0xffffffff;
  e_union_4_state_64(l2);

  l3[2].aval = 1 >> n;
  l3[1].aval = 0xffffffff >> m;
  e_union_4_state_65(l3);

  l4[3].aval = 0xffffffff >> n;
  e_union_4_state_128(l4);

  n++;
}
